Kratos 学习笔记
开发顺序
- 编写 proto 文件,定义 API
- 编写 internal/service 层的代码
- 验证请求
- 调用 biz 层业务逻辑,biz 层需要传入新的 Usecase
- 实现 biz 层调用的 data 层数据库操作实现
- 返回响应
如何在biz层使用配置文件
更改conf.proto
这里添加了App字段,记得添加消息到Bootstarp消息体中
syntax = "proto3";
// 略
message Bootstrap {
Server server = 1;
Data data = 2;
App app = 3;
}
// 略
message App {
string env = 1; // dev test prod
}
生成config代码
在项目根目录执行make config来自动生成配置文件代码
更改依赖注入相关代码
在cmd/krathub/main.go中找到如下代码,添加bc.App结构体
app, cleanup, err := wireApp(bc.Server, bc.Data, bc.App, logger)
if err != nil {
panic(err)
}
随后在wire.go中添加一个名为*conf.App的依赖
// wireApp init kratos application.
func wireApp(*conf.Server, *conf.Data, *conf.App, log.Logger) (*kratos.App, func(), error) {
panic(wire.Build(server.ProviderSet, data.ProviderSet, biz.ProviderSet, service.ProviderSet, newApp))
}
生成依赖注入代码
在main函数的目录中执行wire来生成代码,这样我们自定义的配置文件才能传入进去
在biz层需要配置的地方添加依赖项
在我的代码internal/biz/auth.go中需要用到配置文件,所以需要做如下修改
// AuthUsecase is a Auth usecase.
type AuthUsecase struct {
repo AuthRepo
log *log.Helper
cfg *conf.App // 新增的依赖项,注意结构体名字不能搞错
}
// NewAuthUsecase new an auth usecase. ↓这里就是方法所需依赖
func NewAuthUsecase(repo AuthRepo, logger log.Logger, cfg *conf.App) *AuthUsecase {
return &AuthUsecase{
repo: repo,
log: log.NewHelper(logger),
cfg: cfg,
}
}
此时还没有再次执行依赖注入的程序,只是人为声明了依赖,wire并不知道我们在哪个层的哪个方法使用了我们在wire.go中添加的依赖。所以这个时候去查看cmd/krathub/wire_gen.go中的代码,可以发现wireApp方法已经有一个名为app *conf.App的形参,但是在下方的方法NewAuthUsecase中并没有引用这个形参。
// wireApp init kratos application.
func wireApp(confServer *conf.Server, confData *conf.Data, app *conf.App, logger log.Logger) (*kratos.App, func(), error) { // ↑之前执行wire的时候已经有了这个形参
db, err := data.NewDB(confData)
if err != nil {
return nil, nil, err
}
dataData, cleanup, err := data.NewData(db, confData, logger)
if err != nil {
return nil, nil, err
}
authRepo := data.NewAuthRepo(dataData, logger) // ↓在执行wire前这里没有app参数
authUsecase := biz.NewAuthUsecase(authRepo, logger, app)
authService := service.NewAuthService(authUsecase)
grpcServer := server.NewGRPCServer(confServer, authService, logger)
httpServer := server.NewHTTPServer(confServer, authService, logger)
kratosApp := newApp(logger, grpcServer, httpServer)
return kratosApp, func() {
cleanup()
}, nil
}
所以我们需要再次执行wire命令来重新生成依赖注入代码,这个过程熟悉之后,文中之前提到的初次依赖注入代码就可以不用执行命令,只要本次一次执行即可
使用配置文件
现在已经做完了所有工作,直接用以下代码即可获得所需配置
fmt.Println(uc.cfg.Env)
注意事项
新增业务须知
编写完新的业务之后需要在service、biz和data层的wire方法加入依赖,然后用wire生成代码,最后在server的http和grpc的定义方法中添加相应的service.xxxService才能正常上线业务
三个层的依赖注入代码
internal/service/service.go
var ProviderSet = wire.NewSet(NewAuthService, NewUserService)
internal/biz/biz.go
var ProviderSet = wire.NewSet(NewAuthUsecase, NewUserUsecase)
internal/data/data.go
var ProviderSet = wire.NewSet(NewData, NewDB, NewAuthRepo, NewUserRepo)
文件internal/server/http.go,grpc.go同理
// NewHTTPServer new an HTTP server.
func NewHTTPServer(c *conf.Server, auth *service.AuthService, user *service.UserService, logger log.Logger) *http.Server {
var opts = []http.ServerOption{
http.Middleware(
recovery.Recovery(),
tracing.Server(),
logging.Server(logger),
validate.Validator(),
selector.Server(middleware.Auth()).Match(middleware.AuthWhiteListMatcher()).Build(),
),
}
if c.Http.Network != "" {
opts = append(opts, http.Network(c.Http.Network))
}
if c.Http.Addr != "" {
opts = append(opts, http.Address(c.Http.Addr))
}
if c.Http.Timeout != nil {
opts = append(opts, http.Timeout(c.Http.Timeout.AsDuration()))
}
srv := http.NewServer(opts...)
authV1.RegisterAuthHTTPServer(srv, auth)
userV1.RegisterUserHTTPServer(srv, user)
return srv
}